# 导入日志模块(为了生成日志格式)
import logging
# 导入日志处理模块(为了生成日志记录器)
from logging.handlers import RotatingFileHandler
from flask import Flask
# 导入flask中的mysql数据库扩展
from flask_sqlalchemy import SQLAlchemy
# 导入session扩展,生成session对象
from flask_session import Session
# 导入配置文件
from config import config,Config
# 导入csrf模块，用来保护app
from flask_wtf import CSRFProtect, csrf
# 导入redis数据库模块，创建redis数据库对象
from redis import StrictRedis


# 生成mysql数据库对象
db = SQLAlchemy()

# 生成redis数据库对象,将数据库默认的字节类型的数据转化成字符串数据
redis_store = StrictRedis(host=Config.REDIS_HOST, port=Config.REDIS_PORT, decode_responses=True)


# 创建工厂函数，传入不同的参数，返回不同的flask实例
def create_app(config_name):

    # 创建flask实例
    app = Flask(__name__)

    # 加载配置信息
    app.config.from_object(config[config_name])

    # 调用日志方法(获取DevelopmentConfig类中的level_name方法)
    set_logging(config[config_name].level_name)

    # 将flask程序实例与session对象进行关联(获取session中的相关数据)
    # 此时的redis数据库中就有一条session信息了
    Session(app)

    # 设置csrf，保护app
    CSRFProtect(app)

    # 使用请求钩子，在每一次请求之后，写入到客户端浏览器的cookie中，写入csrf_token
    @app.after_request
    def after_request(response):
        csrf_token = csrf.generate_csrf()
        response.set_cookie('csrf_token', csrf_token)
        return response

    # 导入自定义的过滤器对象
    from info.utils.commons import index_class
    # 将自定义的过滤器添加到过滤器中，使之生效
    app.add_template_filter(index_class, "index_class")

    # 将flask程序实例与db数据库对象进行关联
    db.init_app(app)

    # 注册蓝图对象(新闻首页和新闻标题)
    from info.modules.news import news_blue
    app.register_blueprint(news_blue)

    # 注册蓝图对象（新闻登录页面）
    from info.modules.passport import passport_blue
    app.register_blueprint(passport_blue)

    return app


def set_logging(leve):
    # 设置日志的记录等级(logging.basicConfig函数用来实现打印日志的基础配置)
    # 参数level表示日志的级别，默认是logging.WARNING
    logging.basicConfig(level=leve)  # 调试debug级

    # RotatingFileHandler函数表示，当日志文件存储大小达到一定的值的时候，RotatingFileHandler会将日志文件重新命名，之后打开一个新的日志文件
    # 使用RotatingFileHandler函数创建日志记录器，指明日志保存的路径、每个日志文件的最大大小（这里是100M）,保存的日志文件个数上限（这里是10个）
    file_log_handler = RotatingFileHandler("logs/log", maxBytes=1024 * 1024 * 10, backupCount=10)
    # 创建日志记录的格式 日志等级的名称，调用日志输出模块的文件名 调用日志输出函数的语句所在的代码行 日志信息
    formatter = logging.Formatter('%(levelname)s %(filename)s:%(lineno)d %(message)s')
    # 为刚创建的日志记录器设置日志记录格式
    file_log_handler.setFormatter(formatter)
    # 为全局的日志工具对象（flask app使用的）添加日志记录器
    logging.getLogger().addHandler(file_log_handler)